from pymodbus.server import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
import time
import threading
import argparse
from datetime import datetime

def convert_string_to_registers(input_string):
    """将字符串转换为寄存器值"""
    # 确保字符串长度为偶数
    if len(input_string) % 2 != 0:
        input_string += ' '
    
    registers = []
    for i in range(0, len(input_string), 2):
        try:
            # 将两个字符打包成一个16位寄存器
            high_byte = min(ord(input_string[i]), 255)  # 确保值不超过255
            low_byte = min(ord(input_string[i + 1]), 255)  # 确保值不超过255
            register_value = (high_byte << 8) | low_byte
            # 确保寄存器值在有效范围内
            register_value = min(register_value, 65535)
            registers.append(register_value)
        except Exception as e:
            print(f"转换字符时发生错误: {e}")
            registers.append(0)  # 发生错误时使用0作为默认值
    
    return registers

def update_data(context, message, interval):
    """更新数据的函数"""
    while True:
        try:
            # 获取当前时间戳
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
            # 组合完整消息
            full_message = f"{current_time} | {message}"
            
            # 转换消息为寄存器值
            registers = convert_string_to_registers(full_message)
            
            # 验证所有寄存器值是否在有效范围内
            valid_registers = [min(max(r, 0), 65535) for r in registers]
            
            # 更新保持寄存器的值
            slave = context[0]
            slave.setValues(3, 0, valid_registers)  # 功能码3代表保持寄存器
            
            print(f"已发送: {full_message}")
            time.sleep(interval)  # 按指定间隔发送
        except Exception as e:
            print(f"更新数据时发生错误: {e}")
            time.sleep(1)

def run_server(message, port, interval):
    try:
        # 创建数据存储
        store = ModbusSlaveContext(
            hr=ModbusSequentialDataBlock(0, [0]*200),  # 增加寄存器空间以容纳更长的消息
        )
        context = ModbusServerContext(slaves=store, single=True)
        
        # 在新线程中启动数据更新
        updater = threading.Thread(target=update_data, args=(context, message, interval))
        updater.daemon = True
        updater.start()
        
        # 启动Modbus TCP服务器
        print(f"启动Modbus TCP服务器在端口 {port}...")
        print(f"发送数据: {message}")
        print(f"发送间隔: {interval}秒")
        
        StartTcpServer(
            context=context,
            address=("0.0.0.0", port)
        )
    except Exception as e:
        print(f"服务器启动错误: {e}")
        raise

def parse_arguments():
    parser = argparse.ArgumentParser(description='Modbus TCP服务器')
    parser.add_argument('--message', '-m', 
                      type=str, 
                      default="1280*1024，无目标",
                      help='要发送的数据内容（默认: "1280*1024，无目标"）')
    parser.add_argument('--port', '-p', 
                      type=int, 
                      default=502,
                      help='服务器端口号（默认: 502）')
    parser.add_argument('--interval', '-i', 
                      type=float, 
                      default=1.0,
                      help='发送数据的时间间隔，单位秒（默认: 1.0）')
    return parser.parse_args()

if __name__ == "__main__":
    try:
        args = parse_arguments()
        run_server(args.message, args.port, args.interval)
    except KeyboardInterrupt:
        print("\n服务器已停止")
    except Exception as e:
        print(f"程序错误: {e}")

